/*
 * Serial.cpp
 *
 *  Created on: 25 oct. 2011
 *      Author: yan
 */
#include <stdlib.h>
#include "serial.h"

serial::serial()
{
    Log = logmanager::getInstance();
	port = NULL;
	ErrorCode = Id_Serial;
	messagesend = new QLineEdit();
	InitParam();
}

serial::~serial()
{
	ClosePort();
}

/*
 * @brief OpenPort and return Success
 * or error
 */
int serial::OpenPort()
{
	ClosePort();
	int status = SUCCESS;
	QString PortName = "COM" + QString::number(this->ParamPortQxt.PortCom + 1);
	port = new QextSerialPort(PortName, QextSerialPort::Polling);
	bool EtatPort = port->open(QIODevice::ReadWrite | QIODevice::Unbuffered);
	if (EtatPort)
	{
		if (Log)
			Log->AddMessage(status, OK + Id_Serial, __LINE__, __FILE__,
					PortName + ": " + QObject::tr("Port open"));

		this->port->setBaudRate(ParamPortQxt.Speed);
		this->port->setFlowControl(ParamPortQxt.FlowControl);
		this->port->setParity(ParamPortQxt.Parity);
		this->port->setDataBits(ParamPortQxt.DataBits);
		this->port->setStopBits(STOP_1); // @todo FIX
		this->port->open(QIODevice::ReadWrite);
		this->port->setTimeout(1000);
		port->setDtr(true);
		port->setRts(true);
		port->flush();
	}
	else
	{
		status = CRITICAL;
		if (Log)
			Log->AddMessage(CRITICAL, ErrorCode + NODEVICE + Id_Serial,
					__LINE__, __FILE__,
					Param.Label + " " + PortName + ": " +  QObject::tr("Serial port not present"));	
	}
	return status;
}

/**
 * @brief send data to port
 * @return SUCCESS or WARNING
 */
int serial::sendToPort(QString message)
{
	int i = WARNING;
	message = message + "\n";
	if (this->port->isOpen())
	{
		messagesend->setText(message);
		i = port->write((messagesend->text()).toAscii(),
				messagesend->text().length());
        // @todo changer Sleep en sleep compatible QT
        //Sleep(800);
	}
	return i;
}

/**
 * @brief Read Serial Port
 * @return QString reponse
 */
QString serial::readPort(void)
{
	int numBytes = 0;
	char buff[1024] = { 0 };
	bool bPortIsReady = false;
	QString msg = "";
	bool bNoreply = false;


	this->bSimu_Mode_All = false;
	if (bSimu_Mode_All == FALSE)
	{

		if (this->port->isOpen())
		{
			numBytes = this->port->bytesAvailable();
			//Log->AddMessage(WARNING, ErrorCode + OK, __LINE__, __FILE__,
			//	"bytesAvailable: " + QString::number(numBytes));
			if (numBytes > 1024)
				numBytes = 1024;
			int i = port->read(buff, numBytes);
			if (i != -1)
				buff[i] = '\0';
			else
				buff[0] = '\0';
			msg = buff;
			if (numBytes != 0)
			{
				bNoreply = false;
			}
			else
			{
				msg = "";
				bNoreply = true;
			}
			this->port->flush();
		}
		else
		{

		}
	}
	else
	{

	}
	bPortIsReady = true;
	msg.remove("\n");
	msg.remove("\r");
	return msg;
}

/*
 * @brief Convert type PortCom from IHM to ParamSerialqxt for serial port driver
 *
 * @param[in] data from ihm
 * @param[out]  structure paramSerialqxt for port
 */
int serial::ConvertParamSerial(PortCom PortComfromIhm, ParamSerialqxt &result)
{
	result.PortCom = (PortComLst) PortComfromIhm.Port;
	result.Speed = (BaudRateType) PortComfromIhm.Speed;
	result.DataBits = (DataBitsType) PortComfromIhm.Bits;
	result.StopBits = (StopBitsType) PortComfromIhm.StopBits;
	result.Parity = (ParityType) PortComfromIhm.Parity;
	result.FlowControl = (FlowType) PortComfromIhm.Flow;
	return SUCCESS;
}

/*
 * @brief initialize all parameters
 */
int serial::InitParam()
{
	ParamPortQxt.DataBits = DATA_8;
	ParamPortQxt.FlowControl = FLOW_OFF;
	ParamPortQxt.Parity = PAR_NONE;
	ParamPortQxt.PortCom = COM2;
	ParamPortQxt.Speed = BAUD19200;
	ParamPortQxt.StopBits = STOP_1;

	return SUCCESS;
}

/*
 * @brief close Port
 */
int serial::ClosePort()
{
	if (port != NULL)
	{
		this->port->close();
		free(this->port); //delete port;
		this->port = NULL;
	}
	return SUCCESS;
}

/*
 * @brief Set parameters on port
 *
 * @param[out] port
 * @param[in] parameters
 */
int serial::setParamPort(QextSerialPort *port, ParamSerialqxt ParamPort)
{
	port->setBaudRate(ParamPort.Speed);
	port->setFlowControl(ParamPort.FlowControl);
	port->setParity(ParamPort.Parity);
	port->setDataBits(ParamPort.DataBits);
	port->setStopBits(ParamPort.StopBits);
	port->open(QIODevice::ReadWrite);
	port->setTimeout(1000);
	port->setDtr(true);
	port->setRts(true);
	port->flush();
	return SUCCESS;
}


/**
 * @brief Set parameters port from IMH
 * @param[in] PortCom serial parameters (COMx, speed...)
 */

int serial::setParamPort(PortCom PortCom)
{		
	int status = SUCCESS;
	if (port != NULL)
	{
		if (port->isOpen())
		{
			port->close(); 
		}
	}
	ConvertParamSerial(PortCom,ParamPortQxt);
	status = OpenPort();
	return status;
}




/**
 * @brief get port params
 */
PortCom serial::getParamPort(void)
{
	PortCom result;
	result.Port = this->ParamPortQxt.PortCom;
	result.Flow = this->ParamPortQxt.FlowControl;
	result.Parity = this->ParamPortQxt.Parity;
	result.Bits = this->ParamPortQxt.DataBits;
	result.Speed = this->ParamPortQxt.Speed;
	result.StopBits = this->ParamPortQxt.StopBits;
	return result;
}


/*
 * @brief Convert String to Qxt format structure
 *
 * @param[out] ParamSerialqxt structure
 * @param[in] ParamSerial structure
 */
ParamSerialqxt serial::Convert2(ParamSerial ParamString)
{
	ParamSerialqxt ParamHqx;
	ParamHqx.PortCom = COM1;
	if (ParamString.PortCom == "COM1")
		ParamHqx.PortCom = COM1;
	if (ParamString.PortCom == "COM2")
		ParamHqx.PortCom = COM2;
	if (ParamString.PortCom == "COM3")
		ParamHqx.PortCom = COM3;
	if (ParamString.PortCom == "COM4")
		ParamHqx.PortCom = COM4;
	if (ParamString.PortCom == "COM5")
		ParamHqx.PortCom = COM5;
	if (ParamString.PortCom == "COM6")
		ParamHqx.PortCom = COM6;
	if (ParamString.PortCom == "COM7")
		ParamHqx.PortCom = COM7;
	if (ParamString.PortCom == "COM8")
		ParamHqx.PortCom = COM8;
	if (ParamString.PortCom == "COM9")
		ParamHqx.PortCom = COM9;
	if (ParamString.PortCom == "COM10")
		ParamHqx.PortCom = COM10;
	if (ParamString.PortCom == "COM11")
		ParamHqx.PortCom = COM11;
	if (ParamString.PortCom == "COM12")
		ParamHqx.PortCom = COM12;

	ParamHqx.DataBits = DATA_8;
	if (ParamString.DataBits == "DATA_5")
		ParamHqx.DataBits = DATA_5;
	if (ParamString.DataBits == "DATA_6")
		ParamHqx.DataBits = DATA_6;
	if (ParamString.DataBits == "DATA_7")
		ParamHqx.DataBits = DATA_7;
	if (ParamString.DataBits == "DATA_8")
		ParamHqx.DataBits = DATA_8;

	ParamHqx.Speed = BAUD19200;
	if (ParamString.Speed == "BAUD110")
		ParamHqx.Speed = BAUD110;
	if (ParamString.Speed == "BAUD300")
		ParamHqx.Speed = BAUD300;
	if (ParamString.Speed == "BAUD600")
		ParamHqx.Speed = BAUD600;
	if (ParamString.Speed == "BAUD1200")
		ParamHqx.Speed = BAUD1200;
	if (ParamString.Speed == "BAUD2400")
		ParamHqx.Speed = BAUD2400;
	if (ParamString.Speed == "BAUD4800")
		ParamHqx.Speed = BAUD4800;
	if (ParamString.Speed == "BAUD9600")
		ParamHqx.Speed = BAUD9600;
//	if (ParamString.Speed == "BAUD14400")
//		ParamHqx.Speed = BAUD14400;
	if (ParamString.Speed == "BAUD19200")
		ParamHqx.Speed = BAUD19200;
	if (ParamString.Speed == "BAUD38400")
		ParamHqx.Speed = BAUD38400;
//	if (ParamString.Speed == "BAUD56000")
//		ParamHqx.Speed = BAUD56000;
	if (ParamString.Speed == "BAUD57600")
		ParamHqx.Speed = BAUD57600;
	if (ParamString.Speed == "BAUD57600")
		ParamHqx.Speed = BAUD57600;
	if (ParamString.Speed == "BAUD115200")
		ParamHqx.Speed = BAUD115200;
//	if (ParamString.Speed == "BAUD128000")
//		ParamHqx.Speed = BAUD128000;
//	if (ParamString.Speed == "BAUD256000")
//		ParamHqx.Speed = BAUD256000;

	ParamHqx.FlowControl = FLOW_OFF;
	if (ParamString.FlowControl == "FLOW_OFF")
		ParamHqx.FlowControl = FLOW_OFF;
	if (ParamString.FlowControl == "FLOW_HARDWARE")
		ParamHqx.FlowControl = FLOW_HARDWARE;
	if (ParamString.FlowControl == "FLOW_XONXOFF")
		ParamHqx.FlowControl = FLOW_XONXOFF;

	ParamHqx.StopBits = STOP_1;
	if (ParamString.StopBits == "STOP_1")
		ParamHqx.StopBits = STOP_1;
//	if (ParamString.StopBits == "STOP_1_5")
//		ParamHqx.StopBits = STOP_1_5;
	if (ParamString.StopBits == "STOP_2")
		ParamHqx.StopBits = STOP_2;

	ParamHqx.Parity = PAR_NONE;
	if (ParamString.Parity == "PAR_NONE")
		ParamHqx.Parity = PAR_NONE;
	if (ParamString.Parity == "PAR_ODD")
		ParamHqx.Parity = PAR_ODD;
	if (ParamString.Parity == "PAR_EVEN")
		ParamHqx.Parity = PAR_EVEN;
//	if (ParamString.Parity == "PAR_MARK")
//		ParamHqx.Parity = PAR_MARK;
	if (ParamString.Parity == "PAR_SPACE")
		ParamHqx.Parity = PAR_SPACE;

	return ParamHqx;
}

/*
 * @brief Convert Qxt to String format structure
 *
 * @param[in] ParamSerialqxt structure
 * @param[out] ParamSerial structure
 */
ParamSerial serial::Convert2(ParamSerialqxt Serialqxt)
{
	ParamSerial ParamString;
	ParamString.PortCom = "COM1";
	if (Serialqxt.PortCom == COM1)
		ParamString.PortCom = "COM1";
	if (Serialqxt.PortCom == COM2)
		ParamString.PortCom = "COM2";
	if (Serialqxt.PortCom == COM3)
		ParamString.PortCom = "COM3";
	if (Serialqxt.PortCom == COM4)
		ParamString.PortCom = "COM4";
	if (Serialqxt.PortCom == COM5)
		ParamString.PortCom = "COM5";
	if (Serialqxt.PortCom == COM6)
		ParamString.PortCom = "COM6";
	if (Serialqxt.PortCom == COM7)
		ParamString.PortCom = "COM7";
	if (Serialqxt.PortCom == COM8)
		ParamString.PortCom = "COM8";
	if (Serialqxt.PortCom == COM9)
		ParamString.PortCom = "COM9";
	if (Serialqxt.PortCom == COM10)
		ParamString.PortCom = "COM10";
	if (Serialqxt.PortCom == COM11)
		ParamString.PortCom = "COM11";
	if (Serialqxt.PortCom == COM12)
		ParamString.PortCom = "COM12";

	ParamString.DataBits = "DATA_8";
	if (Serialqxt.DataBits == DATA_5)
		ParamString.DataBits = "DATA_5";
	if (Serialqxt.DataBits == DATA_6)
		ParamString.DataBits = "DATA_6";
	if (Serialqxt.DataBits == DATA_7)
		ParamString.DataBits = "DATA_7";
	if (Serialqxt.DataBits == DATA_8)
		ParamString.DataBits = "DATA_8";

	ParamString.Speed = "BAUD19200";
	if (Serialqxt.Speed == BAUD110)
		ParamString.Speed = "BAUD110";
	if (Serialqxt.Speed == BAUD300)
		ParamString.Speed = "BAUD300";
	if (Serialqxt.Speed == BAUD600)
		ParamString.Speed = "BAUD600";
	if (Serialqxt.Speed == BAUD1200)
		ParamString.Speed = "BAUD1200";
	if (Serialqxt.Speed == BAUD2400)
		ParamString.Speed = "BAUD2400";
	if (Serialqxt.Speed == BAUD4800)
		ParamString.Speed = "BAUD4800";
	if (Serialqxt.Speed == BAUD9600)
		ParamString.Speed = "BAUD9600";
//	if (Serialqxt.Speed == BAUD14400)
//		ParamString.Speed = "BAUD14400";
	if (Serialqxt.Speed == BAUD19200)
		ParamString.Speed = "BAUD19200";
	if (Serialqxt.Speed == BAUD38400)
		ParamString.Speed = "BAUD38400";
//	if (Serialqxt.Speed == BAUD56000)
//		ParamString.Speed = "BAUD56000";
	if (Serialqxt.Speed == BAUD57600)
		ParamString.Speed = "BAUD57600";
	if (Serialqxt.Speed == BAUD115200)
		ParamString.Speed = "BAUD115200";
//	if (Serialqxt.Speed == BAUD128000)
//		ParamString.Speed = "BAUD128000";
//	if (Serialqxt.Speed == BAUD256000)
//		ParamString.Speed = "BAUD256000";

	ParamString.FlowControl = "FLOW_OFF";
	if (Serialqxt.FlowControl == FLOW_OFF)
		ParamString.FlowControl = "FLOW_OFF";
	if (Serialqxt.FlowControl == FLOW_HARDWARE)
		ParamString.FlowControl = "FLOW_HARDWARE";
	if (Serialqxt.FlowControl == FLOW_XONXOFF)
		ParamString.FlowControl = "FLOW_XONXOFF";

	ParamString.StopBits = "STOP_1";
	if (Serialqxt.StopBits == STOP_1)
		ParamString.StopBits = "STOP_1";
//	if (Serialqxt.StopBits == STOP_1_5)
//		ParamString.StopBits = "STOP_1_5";
//	if (Serialqxt.StopBits == STOP_2)
//		ParamString.StopBits = "STOP_2";

	ParamString.Parity = "PAR_NONE";
	if (Serialqxt.Parity == PAR_NONE)
		ParamString.Parity = "PAR_NONE";
	if (Serialqxt.Parity == PAR_ODD)
		ParamString.Parity = "PAR_ODD";
	if (Serialqxt.Parity == PAR_EVEN)
		ParamString.Parity = "PAR_EVEN";
//	if (Serialqxt.Parity == PAR_MARK)
//		ParamString.Parity = "PAR_MARK";
	if (Serialqxt.Parity == PAR_SPACE)
		ParamString.Parity = "PAR_SPACE";

	return ParamString;
}


/**
 * @brief
 *
 * @return QVector<QextSerialPort *>
 */
QVector<QextSerialPort*> serial::ScanSerialPort()
{

    QString PortName ;
    QString label;
    PortName = "COM1";
    QVector<QextSerialPort*> TabValidePort;
    #ifdef __linux__
        PortName = "/dev/ttyUSB0";
        stringOS = "RASPBERRY LINUX";
    #endif
    #ifdef _WIN32
        PortName = "COM4";
        stringOS = "DELL PC WINDOWS";
    #endif



    label.sprintf("========== SCANNING SERIAL DEVICE ==========");
    Log->AddMessage(INFO, 1000 + OK, __LINE__, __FILE__,label);

    QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();

    foreach (QextPortInfo info, ports) {
       label.sprintf("port name: %s",info.portName.toStdString().c_str());
       Log->AddMessage(INFO, 1000 + OK, __LINE__, __FILE__,label);
       label.sprintf("port name: %s",info.friendName.toStdString().c_str());
       Log->AddMessage(INFO, 1000 + OK, __LINE__, __FILE__,label);
       label.sprintf("port name: %s",info.physName.toStdString().c_str());
       Log->AddMessage(INFO, 1000 + OK, __LINE__, __FILE__,label);
       label.sprintf("port name: %s",info.enumName.toStdString().c_str());
       Log->AddMessage(INFO, 1000 + OK, __LINE__, __FILE__,label);
       label.sprintf("port name: %d",info.vendorID);
       Log->AddMessage(INFO, 1000 + OK, __LINE__, __FILE__,label);
       label.sprintf("port name: %d",info.productID);
       label.sprintf("===================================");
       Log->AddMessage(INFO, 1000 + OK, __LINE__, __FILE__,label);
    }

    bool EtatPort = false;
    int nbPort = 0;
    Log->AddMessage(INFO, 1000 + OK, __LINE__, __FILE__,"Searching serial port connected ...");

     // Boucle scan des ports
    for (int i = 0; i < ports.count(); i++)
    {
     if (!ports[i].portName.isEmpty())
     {
         if (port != NULL){ port->close(); free(port);port = NULL;};
         port = new QextSerialPort(ports[i].portName);


         EtatPort =  port->open(QIODevice::ReadWrite | QIODevice::Unbuffered);
         if (EtatPort)
         {
             label = label.sprintf("Serial port %s detected device: %d",
                           ports[i].portName.toStdString().c_str(),
                           ports[i].productID);
             Log->AddMessage(SUCCESS, 1000 + OK, __LINE__, __FILE__,label);
             TabValidePort  << port;
             nbPort++;
         } else
         {
             label = label.sprintf("Serial port %s no device detected",
                           ports[i].portName.toStdString().c_str());
             Log->AddMessage(CRITICAL, 1000 + OK, __LINE__, __FILE__,label);
         }

     }
    }

    label.sprintf("Search for serial port completed: %d port(s) detected",nbPort);
    Log->AddMessage(INFO, 1000 + OK, __LINE__, __FILE__,label);



    if (nbPort > 0)
    {

        //tr("%n item(s) replaced", "", count);
        // label.sprintf(tr("%n serial port detected","",nbPort));
       // emit SendStatusSerial(tr("%n serial(s) port detected","",nbPort),SUCCESS);
    }
    return TabValidePort;
}
